<?php

namespace App\Service\OpenShop\Feishu;


use App\Enums\BaseErrorCode;
use App\Enums\OpenShop\InvestmentPromotion\SignOrderEnum;
use App\Exceptions\Custom\ResponseHttpException;
use App\Http\Middleware\OpenShop\FeishuWebAuth;
use App\Http\Middleware\OpenShop\WangGuiCityByPower;
use App\Models\Common\ConfigModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopMainProcessModel;
use App\Models\OpenShop\InvestmentPromotion\OpenShopSignOrderModel;
use App\Service\BaseService;
use Exception;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Log;
use Illuminate\Validation\ValidationException;

/**
 * @author Green Leaf <786407418@qq.com>
 */
class ConfigService extends BaseService
{
    public static array $configStaticArr = [];

    /**
     * @param string $module
     * @param string $name
     * @return string
     */
    public static function generateConfigStaticKey(string $module = "", string $name = ""): string
    {
        return md5(vsprintf("%s-%s-%s", ["all", $module, $name]));
    }

    /**
     * @return array
     * @throws Exception
     */
    public static function configInfo(): array
    {
        try {
            self::config("openShop");
            $key = self::generateConfigStaticKey("openShop");
            return [
                "source"              => self::$configStaticArr[$key]["source"],
                "joinReason"          => self::$configStaticArr[$key]["joinReason"],
                "investmentMode"      => self::$configStaticArr[$key]["investmentMode"],
                "financeSource"       => self::$configStaticArr[$key]["financeSource"],
                "contractors"         => self::$configStaticArr[$key]["contractors"],
                "contractType"        => self::$configStaticArr[$key]["contractType"],
                "chooseAddressReason" => self::$configStaticArr[$key]["chooseAddressReason"],
                'workLife'            => self::$configStaticArr[$key]["workLife"],
                'hasExperience'       => self::$configStaticArr[$key]["hasExperience"],
                'gender'              => self::$configStaticArr[$key]["gender"],
                'isMarried'           => self::$configStaticArr[$key]["isMarried"],
                'cateringExperience'  => self::$configStaticArr[$key]["cateringExperience"],
                'express'             => self::$configStaticArr[$key]["express"],
                'mode'                => self::$configStaticArr[$key]["mode"],
            ];
        } catch (Exception $exception) {
            handleException($exception, BaseErrorCode::$CODE_GET_CONFIG_FAIL);
        }
    }

    /**
     * @param string $module
     * @param string $name
     * @return array
     * @throws Exception
     */
    public static function config(string $module = "", string $name = ""): array
    {
        try {
            $key = self::generateConfigStaticKey($module, $name);
            if (!isset(self::$configStaticArr[$key])) {
                $data = [];
                ConfigModel::query()
                           ->when($module, function ($query) use ($module) {
                               $query->where("module", $module);
                           })
                           ->when($name, function ($query) use ($name) {
                               $query->where("name", $name);
                           })
                           ->get()->each(function ($item) use (&$data) {
                        switch ($item->type) {
                            case ConfigModel::TYPE_JSON:
                            case ConfigModel::TYPE_ARRAY:
                                $data[$item->name] = json_decode($item->value, true) ?: [];
                                break;
                            case ConfigModel::TYPE_STRING:
                                $data[$item->name] = $item->value ?? '';
                                break;
                            case ConfigModel::TYPE_INT:
                                $data[$item->name] = $item->value ?? 0;
                                break;
                            default:
                                $data[$item->name] = null;
                        }
                    })->toArray();
                self::$configStaticArr[$key] = $data;
            }

            return self::$configStaticArr[$key];
        } catch (Exception $exception) {
            handleException($exception, BaseErrorCode::$CODE_GET_CONFIG_FAIL);
        }
    }


    /**
     * @param string $module
     * @param string $name
     * @param $value
     * @return mixed|string
     * @throws Exception
     */
    public static function getConfigText(string $module, string $name, $value)
    {
        $key = self::generateConfigStaticKey($module);

        if (!isset(self::$configStaticArr[$key])) {
            ConfigService::config($module);
        }

        return (isset(self::$configStaticArr[$key][$name])
            &&
            isset(($configRow = array_column(self::$configStaticArr[$key][$name], "name", "id"))[$value]))
            ? $configRow[$value] : "";
    }

    public static function appEntrance(int $shopId): array
    {
        $myOpenOrder = false;

        $orderNo = OpenShopMainProcessModel::query()->where('shopId', $shopId)->orderBy('id', 'desc')->value('orderNo');
        if ($orderNo) {
            $myOpenOrder = (bool)OpenShopSignOrderModel::query()
                                                       ->where('orderNo', $orderNo)
                                                       ->where('status', '!=', SignOrderEnum::ORDER_STATUS_NO)
                                                       ->count();
        }

        return [
            'myOpenOrder' => $myOpenOrder,
        ];
    }

    public static function save(string $module, string $name, string $value, int $userId): array
    {
        $config = ConfigModel::query()->where('module', $module)->where('name', $name)->first();
        if (!$config) {
            throw new ResponseHttpException(BaseErrorCode::$ERROR_OCCURRED, null, "不存在的config配置");
        }

        Log::info("Config save...", [
            'module'    => $module,
            'name'      => $name,
            'old_value' => $old_value = $config->value,
            'new_value' => $value,
            'userId'    => $userId,
            'createdAt' => date('Y-m-d H:i:s'),
        ]);

        return ['update_row' => $config->update(['value' => $value]), 'old_value' => $old_value, 'new_value' => $value];
    }

    /**
     * 获取配置信息
     *
     * @param string $module
     * @param string $name
     * @param int $cacheTime
     * @return mixed
     * @throws ValidationException
     */
    public static function getConfigDetail(string $module, string $name, int $cacheTime = 0)
    {
        try {
            $configDetailFunc = function () use ($module, $name) {
                $configDetail = ConfigModel::query()
                                           ->where("module", $module)
                                           ->where("name", $name)
                                           ->first();
                if (!$configDetail) {
                    throw new Exception("获取配置失败");
                }

                return [
                    "module"    => $module,
                    "name"      => $name,
                    "createdAt" => $configDetail->createdAt,
                    "updatedAt" => $configDetail->updatedAt,
                    "value"     => jsonToArr($configDetail->getOriginal("value"), $configDetail->getOriginal("value"))
                ];
            };

            if ($cacheTime > 0) {
                return Cache::remember(
                    vsprintf("%s:%s:%s:%d", [__FUNCTION__, $module, $name, $cacheTime]),
                    $cacheTime,
                    function () use ($module, $name, $configDetailFunc) {
                        return $configDetailFunc();
                    }
                );
            } else {
                return $configDetailFunc();
            }
        } catch (Exception $exception) {
            handleException($exception, null, null, "获取配置数据失败");
        }
    }

    public static function getAmapDistrictJson()
    {
        return Cache::remember('tiger:common:amap:district', 864000, function () {
            $url = ConfigService::config('rmsArea',
                'amapAdministrationDistrict')['amapAdministrationDistrict'] ?? 'https://file.51kuafu.com/df/59/5f812ec6b2d4ccefb25fbfe9bb034878bc6bd693ff08cdc853e479915533.json';
            return json_decode(file_get_contents($url), JSON_UNESCAPED_UNICODE);
        });
    }

    /**
     * 工单进件2.0 按分公司信息区分处理人
     * @return mixed
     */
    public static function getManagerUserIdByArea()
    {
        return Cache::remember(
            'tiger:workOrder:getManagerUserIdByArea', getSwitchCacheTime(86400), function () {
            return json_decode(
                ConfigModel::query()
                           ->where('module', 'workOrder')
                           ->where('name', 'getManagerUserIdByArea')
                           ->value('value') ?? [], true
            );
        }
        );
    }

    /**
     * 工单进件2.0 按省信息区分处理人
     * @return mixed
     */
    public static function getManagerUserIdByProvince()
    {
        return Cache::remember(
            'tiger:workOrder:getManagerUserIdByProvince', getSwitchCacheTime(86400), function () {
            return json_decode(
                ConfigModel::query()
                    ->where('module', 'workOrder')
                    ->where('name', 'getManagerUserIdByProvince')
                    ->value('value') ?? '', true
            );
        }
        );
    }




    /**
     * 省市区匹配规范
     * @return array
     */
    public static function regionMatchSpecs(): array
    {
        return Cache::remember('tiger:region:match:specs', 86400 * 120, function () {
            $region = WangGuiCityByPower::getChinaDistrict();
            $data   = [];
            foreach ($region as $province) {
                if (in_array(mb_substr($province['name'], 0, 2), ['台湾', '香港', '澳门'])) {
                    continue;
                }

                $data[] = [
                    'label'    => $province['name'],
                    'parentId' => 0,
                    'value'    => (int)$province['adcode'],
                    'children' => collect($province['districts'])->map(function ($city) use ($province) {
                        return [
                            'label'    => str_replace('城区', '市', $city['name']),
                            'parentId' => (int)$province['adcode'],
                            'value'    => (int)$city['adcode'],
                            'children' => collect($city['districts'])->map(function ($district) use ($city) {
                                if ($district['level'] == 'street') {
                                    return [
                                        'label'    => $city['name'],
                                        'parentId' => (int)$city['adcode'],
                                        'value'    => (int)$city['adcode'],
                                    ];
                                }
                                return [
                                    'label'    => $district['name'],
                                    'parentId' => (int)$city['adcode'],
                                    'value'    => (int)$district['adcode'],
                                ];
                            })->unique()->values()->toArray()
                        ];
                    })->values()->toArray()
                ];
            }

            return array_values($data);
        });
    }

    /**
     * 工单进件2.0 微信/支付宝认证图片配置
     * @return mixed
     */
    public static function getChannelAuthorizeConfig()
    {
        return Cache::remember(
            'tiger:workOrder:getChannelAuthorizeConfig', getSwitchCacheTime(86400), function () {
            return json_decode(
                ConfigModel::query()
                    ->where('module', 'workOrder')
                    ->where('name', 'getChannelAuthorizeConfig')
                    ->value('value') ?? '', true
            );
        }
        );
    }

    public static function publicConfig(string $module, string $name, int $cacheTime): array
    {
        return Cache::remember('tiger:public:config:' . $module . ':' . $name, $cacheTime,
            function () use ($module, $name) {

                $data = ConfigModel::query()->where('module', $module)->where('name', $name)
                                   ->where('public', ConfigModel::IS_PUBLIC)
                                   ->select('module', 'name', 'description', 'type', 'value')->first();
                if (!$data) {
                    return [];
                }

                if ($data->getAttribute('type') == 'json') {
                    $data->value = json_decode($data->getAttribute('value'), true);
                }

                return $data->toArray();
            });
    }
}
